package com.aliang.shopping.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.aliang.shopping.common.Result;
import com.aliang.shopping.common.ResultCodeEnum;
import com.aliang.shopping.contact.ResultMsgContact;
import com.aliang.shopping.exception.DataException;
import com.aliang.shopping.exception.ServiceException;
import com.aliang.shopping.log.annotation.OperateLog;
import com.aliang.shopping.log.enums.OperateType;
import com.aliang.shopping.model.converter.CartConverter;
import com.aliang.shopping.model.dto.common.UpdateStatusDTO;
import com.aliang.shopping.model.po.Cart;
import com.aliang.shopping.model.po.GoodsSku;
import com.aliang.shopping.model.vo.cart.CartShowVO;
import com.aliang.shopping.security.PreventRepeatSubmit;
import com.aliang.shopping.security.auth.UserHolder;
import com.aliang.shopping.service.CartService;
import com.aliang.shopping.service.GoodsSkuService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/cart")
@AllArgsConstructor
public class CartController {

    private final CartService cartService;
    private final CartConverter cartConverter;

    /**
     * 购物车添加
     *
     * @param insertDTO
     * @return
     */
    @PostMapping("/insert")
    @ApiOperation("购物车添加")
    @PreventRepeatSubmit
    @OperateLog(title = "购物车添加", type = OperateType.INSERT)
    @Transactional(rollbackFor = Exception.class)
    public Result<String> insertCart(@RequestBody UpdateStatusDTO insertDTO) {
        //必要字段校验
        if (BeanUtil.hasNullField(insertDTO)) {
            throw new DataException(ResultCodeEnum.DATA_LACK);
        }
        //转换数据
        Cart cart = this.cartConverter.toPoByInsertDTO(insertDTO);
        //获取库存和预存库存，判断该sku的库存是否够
        GoodsSku one = this.goodsSkuService.getOne(
                new LambdaQueryWrapper<GoodsSku>()
                        .select(GoodsSku::getStore, GoodsSku::getReservedStore)
                        .eq(GoodsSku::getId, cart.getGoodsSkuId())
        );
        if (one.getStore() < cart.getGoodsNum()) {
            // 商品库存不足
            throw new DataException(ResultCodeEnum.GOODS_STOCK_NOT_ENOUGH);
        }
        //获取当前登录用户对象Id
        Long userId = UserHolder.getUserId();
        //设置创建人Id
        cart.setUserId(userId);
        // 判断用户是否已添加该规格的商品
        Cart one1 = this.cartService.getOne(new LambdaQueryWrapper<Cart>()
                .select(Cart::getId, Cart::getGoodsNum)
                .eq(Cart::getUserId, userId)
                .eq(Cart::getGoodsSkuId, cart.getGoodsSkuId())
        );
        if (ObjectUtil.isNotNull(one1)) {
            //该规格已添加，更新库存
            one1.setGoodsNum(one1.getGoodsNum() + cart.getGoodsNum());
            this.cartService.updateById(one1);
        } else
            this.cartService.save(cart);
        // 更新sku库存
        GoodsSku goodsSku = new GoodsSku();
        goodsSku.setId(cart.getGoodsSkuId());
        // 库存-1
        goodsSku.setStore(one.getStore() - cart.getGoodsNum());
        //预存库存+1
        goodsSku.setReservedStore(one.getReservedStore() + cart.getGoodsNum());
        boolean skuSave = this.goodsSkuService.updateById(goodsSku);
        // 返回数据
        return skuSave ? Result.ok(ResultMsgContact.CART_ADD_SUC) : Result.fail("").message(ResultMsgContact.INSERT_FAIL);
    }

    /**
     * 购物车删除
     *
     * @param ids
     * @return
     */
    @DeleteMapping("/del")
    @ApiOperation("购物车删除")
    @PreventRepeatSubmit
    @OperateLog(title = "购物车删除", type = OperateType.DELETE)
    @Transactional(rollbackFor = Exception.class)
    public Result<String> delCart(@RequestBody List<Long> ids) {

        //获取购物车数据
        List<Cart> carts = this.cartService.list(
                new LambdaQueryWrapper<Cart>()
                        .select(Cart::getGoodsSkuId, Cart::getGoodsNum)
                        .in(Cart::getId, ids));
        // 获取skuId和商品数量
        Map<Long, Integer> skuMap = carts.stream().collect(Collectors.toMap(Cart::getGoodsSkuId, Cart::getGoodsNum));

        // 获取sku数据
        List<GoodsSku> goodsSkus = this.goodsSkuService.list(
                new LambdaQueryWrapper<GoodsSku>()
                        .select(GoodsSku::getId, GoodsSku::getStore, GoodsSku::getReservedStore)
                        .in(GoodsSku::getId, skuMap.keySet())
        );
        // 更新sku库存
        goodsSkus.forEach(
                goodsSku -> {
                    // 更新库存
                    goodsSku.setStore(goodsSku.getStore() + skuMap.get(goodsSku.getId()));
                    // 更新预存库存
                    goodsSku.setReservedStore(goodsSku.getReservedStore() - skuMap.get(goodsSku.getId()));
                    this.goodsSkuService.updateById(goodsSku);
                }
        );
        //删除购物车数据
        boolean del = this.cartService.removeByIds(ids);
        return Result.ok(ResultMsgContact.DELETE_SUCCESS);
    }

    /**
     * 购物车数量更改
     *
     * @param updateDTO
     * @return
     */
    @PutMapping("/update_num")
    @ApiOperation("购物车数量更改")
    @PreventRepeatSubmit
    @OperateLog(title = "购物车数量更改", type = OperateType.UPDATE)
    @Transactional(rollbackFor = Exception.class)
    public Result<String> updateCartNum(@RequestBody UpdateStatusDTO updateDTO) {
        //必要字段校验
        if (BeanUtil.hasNullField(updateDTO)) throw new DataException(ResultCodeEnum.DATA_LACK);
        //转换数据
        Cart cart = this.cartConverter.toPoByUpdateDTO(updateDTO);
        // 获取当前用户Id
        cart.setUserId(UserHolder.getUserId());
        //根据购物车查询购物车数据
        Cart one = this.cartService.getOne(
                new LambdaQueryWrapper<Cart>()
                        .eq(Cart::getId, cart.getId())
                        .eq(Cart::getUserId, cart.getUserId())
        );
        // 获取sku数据
        GoodsSku goodsSku = this.goodsSkuService.getOne(
                new LambdaQueryWrapper<GoodsSku>()
                        .select(GoodsSku::getStore, GoodsSku::getReservedStore)
                        .eq(GoodsSku::getId, one.getGoodsSkuId())
        );
        // 判断是新增还是删除
        int i = cart.getGoodsNum() - one.getGoodsNum();
        if (i > 0) {
            //新增购物车数量
            if (goodsSku.getStore() < i) {
                // 商品库存不足
                throw new DataException(ResultCodeEnum.GOODS_STOCK_NOT_ENOUGH);
            }
        } else {
            // 删除购物车数量，更新sku库存
            //库存加数量
            goodsSku.setStore(goodsSku.getStore() + (-i));
            // 预存库存加数量
            goodsSku.setStore(goodsSku.getReservedStore() + i);
        }

        //更新数据
        boolean b = this.cartService.updateById(cart);
        return Result.ok(ResultMsgContact.UPDATE_SUCCESS);
    }


    private final GoodsSkuService goodsSkuService;

    /**
     * 获取全部购物车信息
     */
    @GetMapping("/getCartList")
    @ApiOperation("获取全部购物车信息")
    public Result<List<CartShowVO>> getCartList() {
        // 获取当前登录用户Id
        Long userId = UserHolder.getUserId();
        if (ObjectUtil.isNull(userId)) {
            throw new ServiceException(ResultCodeEnum.USER_NOT_LOGIN);
        }
        //查询数据
        List<CartShowVO> cartShowVOList = this.cartService.getCartShowVO(userId);
        //返回数据
        return Result.ok(cartShowVOList);
    }
}
